// 路由级代码分割和懒加载配置

import { lazy, ComponentType } from 'react';

// 懒加载包装器类型
export interface LazyComponentConfig {
  component: () => Promise<{ default: ComponentType<any> }>;
  preload?: boolean; // 是否预加载
  priority?: 'high' | 'normal' | 'low'; // 加载优先级
  fallback?: ComponentType; // 加载失败时的降级组件
}

// 预加载策略类型
export interface PreloadStrategy {
  onHover: boolean;  // 悬停时预加载
  onIdle: boolean;   // 空闲时预加载
  priority: 'high' | 'normal' | 'low';
  timeout?: number;  // 预加载超时时间
}

// 代码分割路由配置
export interface CodeSplitRouteConfig {
  path: string;
  componentConfig: LazyComponentConfig;
  preloadStrategy?: PreloadStrategy;
  chunkName?: string; // Webpack chunk 名称
}

// 懒加载组件注册表
const lazyComponents = new Map<string, {
  component: ComponentType<any>;
  isLoaded: boolean;
  loadPromise?: Promise<ComponentType<any>>;
}>();

// 预加载缓存
const preloadCache = new Set<string>();

/**
 * 创建懒加载组件
 */
export function createLazyComponent(
  importFn: () => Promise<{ default: ComponentType<any> }>,
  chunkName?: string
): ComponentType<any> {
  const LazyComponent = lazy(importFn);
  
  // 注册组件
  if (chunkName) {
    lazyComponents.set(chunkName, {
      component: LazyComponent,
      isLoaded: false,
      loadPromise: undefined
    });
  }
  
  return LazyComponent;
}

/**
 * 预加载组件
 */
export async function preloadComponent(
  importFn: () => Promise<{ default: ComponentType<any> }>,
  chunkName?: string
): Promise<ComponentType<any> | null> {
  try {
    if (chunkName && preloadCache.has(chunkName)) {
      console.log(`[代码分割] 组件 ${chunkName} 已预加载，跳过`);
      return null;
    }

    console.log(`[代码分割] 开始预加载组件: ${chunkName || '未命名'}`);
    const startTime = performance.now();
    
    const module = await importFn();
    const component = module.default;
    
    const loadTime = performance.now() - startTime;
    console.log(`[代码分割] 组件预加载完成: ${chunkName || '未命名'}, 耗时: ${loadTime.toFixed(2)}ms`);
    
    if (chunkName) {
      preloadCache.add(chunkName);
      if (lazyComponents.has(chunkName)) {
        lazyComponents.get(chunkName)!.isLoaded = true;
      }
    }
    
    return component;
  } catch (error) {
    console.error(`[代码分割] 预加载组件失败: ${chunkName || '未命名'}`, error);
    return null;
  }
}

/**
 * 智能预加载策略
 */
export class SmartPreloader {
  private preloadQueue: Array<{
    importFn: () => Promise<{ default: ComponentType<any> }>;
    chunkName?: string;
    priority: 'high' | 'normal' | 'low';
  }> = [];
  
  private isProcessing = false;
  private idleCallbackId?: number;

  /**
   * 添加预加载任务
   */
  addPreloadTask(
    importFn: () => Promise<{ default: ComponentType<any> }>,
    chunkName?: string,
    priority: 'high' | 'normal' | 'low' = 'normal'
  ): void {
    // 避免重复添加
    if (chunkName && preloadCache.has(chunkName)) {
      return;
    }
    
    this.preloadQueue.push({ importFn, chunkName, priority });
    this.sortQueue();
    this.processQueue();
  }

  /**
   * 按优先级排序队列
   */
  private sortQueue(): void {
    const priorityOrder = { high: 3, normal: 2, low: 1 };
    this.preloadQueue.sort((a, b) => priorityOrder[b.priority] - priorityOrder[a.priority]);
  }

  /**
   * 处理预加载队列
   */
  private async processQueue(): Promise<void> {
    if (this.isProcessing || this.preloadQueue.length === 0) {
      return;
    }

    this.isProcessing = true;

    try {
      while (this.preloadQueue.length > 0) {
        const task = this.preloadQueue.shift()!;
        
        // 等待浏览器空闲时执行低优先级任务
        if (task.priority === 'low') {
          await this.waitForIdle();
        }
        
        await preloadComponent(task.importFn, task.chunkName);
        
        // 避免阻塞主线程
        await new Promise(resolve => setTimeout(resolve, 0));
      }
    } catch (error) {
      console.error('[代码分割] 预加载队列处理失败:', error);
    } finally {
      this.isProcessing = false;
    }
  }

  /**
   * 等待浏览器空闲
   */
  private waitForIdle(): Promise<void> {
    return new Promise(resolve => {
      if ('requestIdleCallback' in window) {
        this.idleCallbackId = requestIdleCallback(() => resolve());
      } else {
        setTimeout(resolve, 16); // 降级为 setTimeout
      }
    });
  }

  /**
   * 清除预加载队列
   */
  clearQueue(): void {
    this.preloadQueue = [];
    if (this.idleCallbackId) {
      cancelIdleCallback(this.idleCallbackId);
    }
  }

  /**
   * 获取队列状态
   */
  getQueueStatus(): { pending: number; completed: number } {
    return {
      pending: this.preloadQueue.length,
      completed: preloadCache.size
    };
  }
}

// 全局预加载器实例
export const smartPreloader = new SmartPreloader();

/**
 * 悬停预加载Hook
 */
export function useHoverPreload(
  importFn: () => Promise<{ default: ComponentType<any> }>,
  chunkName?: string,
  enabled: boolean = true
): {
  onMouseEnter: () => void;
  onMouseLeave: () => void;
} {
  const onMouseEnter = () => {
    if (enabled && chunkName && !preloadCache.has(chunkName)) {
      smartPreloader.addPreloadTask(importFn, chunkName, 'high');
    }
  };

  const onMouseLeave = () => {
    // 可以在这里实现取消预加载的逻辑
  };

  return { onMouseEnter, onMouseLeave };
}

/**
 * 空闲时预加载Hook
 */
export function useIdlePreload(
  components: Array<{
    importFn: () => Promise<{ default: ComponentType<any> }>;
    chunkName?: string;
  }>,
  enabled: boolean = true
): void {
  if (!enabled) return;

  // 页面加载完成后的空闲时间进行预加载
  setTimeout(() => {
    components.forEach(({ importFn, chunkName }) => {
      smartPreloader.addPreloadTask(importFn, chunkName, 'low');
    });
  }, 2000); // 延迟2秒，确保页面已稳定
}

/**
 * 获取组件加载状态
 */
export function getComponentLoadStatus(chunkName: string): {
  isLoaded: boolean;
  isPreloaded: boolean;
} {
  return {
    isLoaded: lazyComponents.get(chunkName)?.isLoaded || false,
    isPreloaded: preloadCache.has(chunkName)
  };
}

/**
 * 清除所有预加载缓存
 */
export function clearPreloadCache(): void {
  preloadCache.clear();
  lazyComponents.clear();
  smartPreloader.clearQueue();
  console.log('[代码分割] 预加载缓存已清除');
}